# -*- coding: UTF-8 -*-
__author__ = 'chzhu'

import sqlalchemy
from sqlalchemy import Table
from sqlalchemy.ext.declarative import declarative_base
from Config import Config
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class Database(object):

    dbo = None

    def __new__(cls, *args, **kwargs):
        if not cls.dbo:
            cls.dbo = super(Database, cls).__new__(cls, *args, **kwargs)
            cls.dbo.engine_info = 'mysql+pymysql://' + Config.user + ':' + Config.passwd + '@' + Config.host + '/' + Config.database + '?charset=' + Config.charset
            cls.dbo.engine = sqlalchemy.create_engine(cls.dbo.engine_info)
        return cls.dbo


    def connect(self):
        self.connection = self.engine.connect()
        Session = sessionmaker(bind=self.engine, autocommit=True)
        self.session = Session()

    def close(self):
        self.session.close()
        self.connection.close()

    def commit(self):
        try:
            self.session.commit()
        except Exception as e:
            print 'commit @Database in database.py:', e

Database() # singleton

class Proxy(Base):
    tbName = Config.tables['Proxy']
    engine_info = Database.dbo.engine_info

    engine = sqlalchemy.create_engine(engine_info)
    __table__ = Table(tbName, Base.metadata, autoload=True, autoload_with=engine)

    def __init__(self, attrs):
        for key, value in attrs.items():
            setattr(self, key, value)

    @classmethod
    def randOne(cls):
        with Database.dbo.session.begin():
            result = Database.dbo.session.query(cls).filter(cls.is_available == '1').first()
            result.is_available = '0'
        cls.reset_proxies()
        return result

    @classmethod
    def reset_proxies(cls):
        with Database.dbo.session.begin():
            result = Database.dbo.session.query(cls).filter(cls.is_available == '1').all()
            if len(result) == 0:
                result = Database.dbo.session.query(cls).filter(cls.is_available == '0').all()
                for res in result:
                    res.is_available = '1'
                print 'Reset all proxies!'

    def report(self):
        with Database.dbo.session.begin():
            self.is_available = '1'


class Cookie(Base):
    tbName = Config.tables['Cookie']
    engine_info = Database.dbo.engine_info

    engine = sqlalchemy.create_engine(engine_info)
    __table__ = Table(tbName, Base.metadata, autoload=True, autoload_with=engine)

    def __init__(self, attrs):
        for key, value in attrs.items():
            setattr(self, key, value)

    @classmethod
    def randOne(cls):
        with Database.dbo.session.begin():
            result = Database.dbo.session.query(cls).filter(cls.is_available == '1').first()
            result.is_available = '0'
            result
        cls.reset_cookies()
        return result
    @classmethod
    def reset_cookies(cls):
        with Database.dbo.session.begin():
            result = Database.dbo.session.query(cls).filter(cls.is_available == '1', cls.is_expired == '0').all()
            if len(result) == 0:
                result = Database.dbo.session.query(cls).filter(cls.is_available == '0', cls.is_expired == '0').all()
                for res in result:
                    res.is_available = '1'
                print 'Reset all cookies!'

    def report(self):
        with Database.dbo.session.begin():
            self.is_available = '1'


class Timeline(Base):
    __table__ = Table(Config.tables['Timeline'], Base.metadata, autoload=True, autoload_with=Database.dbo.engine)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)

class Uid(Base):
    __table__ = Table(Config.tables['Uid'], Base.metadata, autoload=True, autoload_with=Database.dbo.engine)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)

    @classmethod
    def get_by_id(cls, id):
        with Database.dbo.session.begin():
            cursor = Database.dbo.session.query(cls).filter(cls.cid == id).all()
            result = []
            for c in cursor:
                result.append(c)
        return result

    @classmethod
    def get_all(cls):
        with Database.dbo.session.begin():
            result = Database.dbo.session.query(cls).filter().all()
            return result

    @classmethod
    def get_uids(cls, num):
        with Database.dbo.session.begin():
            cursor = Database.dbo.session.query(cls).filter(cls.is_available == '1').limit(num)
            results = []
            for cr in cursor:
                cr.is_available = '0'
                results.append(cr)
        return results

